package com.itheima.easy.service.impl;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.itheima.easy.base.AjaxResult;
import com.itheima.easy.base.PageResponse;
import com.itheima.easy.constant.AccraditationRecordConstant;
import com.itheima.easy.constant.PendingTasksConstant;
import com.itheima.easy.constant.RetreatConstant;
import com.itheima.easy.dto.RetreatClearingBillDto;
import com.itheima.easy.dto.RetreatDto;
import com.itheima.easy.dto.RetreatReqDto;
import com.itheima.easy.entity.*;
import com.itheima.easy.enums.Applications;
import com.itheima.easy.exception.BaseException;
import com.itheima.easy.handler.CommonPayHandler;
import com.itheima.easy.mapper.*;
import com.itheima.easy.service.BalanceService;
import com.itheima.easy.service.BillService;
import com.itheima.easy.service.RetreatService;
import com.itheima.easy.utils.CodeUtil;
import com.itheima.easy.utils.StringUtils;
import com.itheima.easy.utils.UserThreadLocal;
import com.itheima.easy.vo.BalanceVo;
import com.itheima.easy.vo.TradingVo;
import com.itheima.easy.vo.UserRoleVo;
import com.itheima.easy.vo.retreat.DueBack;
import com.itheima.easy.vo.retreat.RetreatBillVo;
import com.itheima.easy.vo.retreat.RetreatVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author sjqn
 * @date 2023/6/19
 */
@Service
public class RetreatServiceImpl implements RetreatService {

    private static final String RETREAT_CODE_PREFIX = "TZ";

    private static final String RECORD_STEP_NO_PRE = "RECORD:";

    @Autowired
    private RetreatMapper retreatMapper;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private PendingTasksMapper pendingTasksMapper;

    @Autowired
    private AccraditationRecordMapper accraditationRecordMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private ApplicationsMapper applicationsMapper;

    /**
     * 退住申请
     *
     * @param retreat
     */
    @Override
    @Transactional
    public AjaxResult createRetreat(Retreat retreat) {

        //1.验证状态
        Long elderId = retreat.getElderId();
        Retreat dbRetreat = retreatMapper.selectByElderId(elderId);
        if (dbRetreat != null && retreat.getFlowStatus() == null) {
            return AjaxResult.error(dbRetreat.getName() + "已经发起了申请退住");
        }
        //从当前线程中获取用户数据
        String subject = UserThreadLocal.getSubject();
        User user = JSON.parseObject(subject, User.class);

        //找到申请人部门，通过部门找到对应的负责人
        List<DeptPostUser> deptPostUserList = deptPostUserMapper.findDeptPostUserByUserId(user.getId());
        DeptPostUser deptPostUser = deptPostUserList.get(0);
        //申请人部门编号
        String deptNo = deptPostUser.getDeptNo();

        //退住标题
        String title = retreat.getName() + "的退住申请";

        //设置流程状态
        retreat.setFlowStatus(Retreat.FlowStatus.APPLY_APPROVAL.getCode());
        retreat.setStatus(Retreat.Status.APPLICATION.getCode());
        if (retreat.getRetreatCode() != null) {
            if (!user.getId().equals(retreat.getApplicatId())) {
                return AjaxResult.error("不是申请人，不是能提交数据");
            }
            //申请人的名字
            retreat.setTitle(title);
            //修改
            retreatMapper.update(retreat);

            //修改我的申请
            Applications applications = applicationsMapper.selectByCode(retreat.getRetreatCode());
            applications.setTitle(title);
            applicationsMapper.update(applications);

        } else {
            retreat.setApplicat(user.getRealName());
            retreat.setApplicatId(user.getId());
            //创建时间
            retreat.setCreateTime(LocalDateTime.now());
            retreat.setTitle(title);
            retreat.setCreateBy(user.getId());//创建人
            retreat.setStatus(Retreat.Status.APPLICATION.getCode());
            //设置下个操作人
            String retreatCode = CodeUtil.generateCode(RETREAT_CODE_PREFIX, redisTemplate, 5);
            retreat.setRetreatCode(retreatCode);
            retreat.setDeptNo(deptNo);
            //设置下一个状态
            retreatMapper.createRetreat(retreat);

            //保存我的申请
            Applications applications = new Applications();
            applications.setApplicat(user.getRealName());
            applications.setApplicationTime(retreat.getCreateTime());
            applications.setApplicatId(user.getId());
            applications.setCode(retreatCode);
            applications.setStatus(Retreat.Status.APPLICATION.getCode());
            applications.setTitle(title);
            applications.setType(PendingTasksConstant.TASK_TYPE_RETREAT);
            applicationsMapper.insert(applications);
        }
        //记录操作记录
        AccraditationRecord accraditationRecord = new AccraditationRecord();
        accraditationRecord.setApproverId(user.getId());
        accraditationRecord.setHandleType(AccraditationRecordConstant.RECORD_HANDLE_TYPE_PROCESSED);
        accraditationRecord.setBussniessId(retreat.getId());
        accraditationRecord.setCreateTime(LocalDateTime.now());
        accraditationRecord.setType(AccraditationRecordConstant.RECORD_TYPE_RETREAT);
        accraditationRecord.setApproverName(user.getRealName());
        accraditationRecord.setCurrentStep("发起申请-申请退住");
        accraditationRecord.setAuditStatus(AccraditationRecordConstant.AUDIT_STATUS_PASS);
        accraditationRecord.setStepNo(redisTemplate.boundValueOps(RECORD_STEP_NO_PRE + retreat.getId()).increment());

        Dept dept = deptMapper.selectByDeptNo(deptNo);
        //部门领导id
        Long leaderId = dept.getLeaderId();

        //查询下一个审核人的姓名和角色
        List<UserRoleVo> userRoleVoList = userRoleMapper.selectByUserId(leaderId);
        //待办任务，下个节点审核人 设置下个操作人--->法务
        UserRoleVo userRoleVo = userRoleVoList.get(0);

        //审核记录，设置下个节点审核人的角色和用户名
        accraditationRecord.setNextApprover(userRoleVo.getUserName());
        List<String> roleNameList = userRoleVoList.stream().map(x -> x.getRoleName()).collect(Collectors.toList());
        accraditationRecord.setNextApproverRole(StringUtils.join(roleNameList, ","));
        accraditationRecord.setNextApproverId(userRoleVo.getId());
        //保存审核（操作）记录
        accraditationRecordMapper.insert(accraditationRecord);

        //设置待办
        PendingTasks pendingTasks = pendingTasksMapper.selectByCodeAndAssinessId(retreat.getRetreatCode(), userRoleVo.getId());
        if (pendingTasks != null) {
            pendingTasksMapper.updateIsHandle(retreat.getRetreatCode(), PendingTasksConstant.TASK_IS_HANDLE_UNTREATED, userRoleVo.getId());
        } else {
            pendingTasks = getPendingTasks(retreat, RetreatConstant.ACCRADITATION_STEP_NO_ONE);
            pendingTasks.setAssignee(userRoleVo.getUserName());
            pendingTasks.setAssigneeId(userRoleVo.getId());
            pendingTasksMapper.insert(pendingTasks);
        }

        return AjaxResult.success("提交成功");
    }

    @Autowired
    private DeptPostUserMapper deptPostUserMapper;

    @Autowired
    private DeptMapper deptMapper;

    @Autowired
    private RescissionContractMapper rescissionContractMapper;

    @Autowired
    private BillService billService;

    @Autowired
    private RetreatBillMapper retreatBillMapper;

    /**
     * 查询退住信息
     *
     * @param retreatCode 退住单号
     * @param assigneeId  审核人
     * @return
     */
    @Override
    public AjaxResult<RetreatVo> getRetreat(String retreatCode, String assigneeId, Integer flowStatus) {

        //当前登录人id
        Long mgtUserId = UserThreadLocal.getMgtUserId();
        //需要返回到前端的数据
        RetreatVo vo = new RetreatVo();

        //查询退住单数据
        Retreat retreat = retreatMapper.getRetreatByCode(retreatCode);
        //审批记录数据
        List<AccraditationRecord> accraditationRecordList = accraditationRecordMapper.getAccraditationRecordByBuisId(retreat.getId());
        vo.setAccraditationRecords(accraditationRecordList);
        vo.setRetreat(retreat);
        //默认显示退住数据
        vo.setIsShow(1);

        //默认不显示撤回按钮
        vo.setIsRevocation(false);

        //当前退住单状态
        Integer dbFlowstatus = retreat.getFlowStatus();

        //申请人撤回单独处理，如果前端传递过来的流程状态0(申请人状态),数据库目前的流程状态为1(护理组长待审批状态) 且 操作人是申请人  则显示撤回
        if (dbFlowstatus.equals(Retreat.FlowStatus.APPLY_APPROVAL.getCode())
                && retreat.getApplicatId().equals(mgtUserId)
                && flowStatus.equals(Retreat.FlowStatus.APPLY.getCode())
                && retreat.getStatus().equals(Retreat.Status.APPLICATION.getCode())) {
            vo.setIsRevocation(true);
        }

        //状态为2-7撤回按钮显示,数据库流程状态回退一步，与传递过来的状态相等 且 前端传递过来的状态不为-1（默认跳转为-1）
        //且当前操作人是待办任务中的上一个执行人
        if ((dbFlowstatus - 1) == flowStatus
                && flowStatus != -1
                && retreat.getStatus().equals(Retreat.Status.APPLICATION.getCode())) {
            PendingTasks pendingTasks = pendingTasksMapper.selectByCodeAndStepNo(retreat.getRetreatCode(), dbFlowstatus);
            if (pendingTasks != null && mgtUserId.equals(pendingTasks.getAssigneeId())) {
                vo.setIsRevocation(true);
            }
        }

        //查询解除协议
        RescissionContract rescissionContract = rescissionContractMapper.selectByRetreatId(retreat.getId());
        vo.setRescissionContract(rescissionContract);

        //如果状态为3:结算员调整账单，则需要查询账单列表
        if (dbFlowstatus.equals(Retreat.FlowStatus.RECONCILIATION_BILL.getCode())) {
            //账单列表
            RetreatBillVo retreatBillVo = billService.retreatSettlement(retreat.getElderId(), retreat.getCheckOutTime());
            vo.setRetreatBillVo(retreatBillVo);
        }

        //状态大于3 且 小于6 ，为结算审批、院长审批两个状态显示的账单内容
        if (dbFlowstatus > 3 && dbFlowstatus < 6) {
            RetreatBill retreatBill = retreatBillMapper.selectByRetreatId(retreat.getId());
            if (retreatBill != null && StringUtils.isNotEmpty(retreatBill.getBillJson())) {
                RetreatBillVo billVo = JSONUtil.toBean(retreatBill.getBillJson(), RetreatBillVo.class);
                vo.setRetreatBillVo(billVo);
            }
        }

        //展示最终账单数据(计算算清费用最终的账单显示)
        if (dbFlowstatus.equals(Retreat.FlowStatus.BILL_SETTLEMENT.getCode())) {
            //退款金额、预缴款金额
            RetreatBillVo retreatBillVo = billService.retreatSettlement(retreat.getElderId(), retreat.getCheckOutTime());
            vo.setRetreatBillVo(retreatBillVo);
        }

        //查询待办任务
        PendingTasks pendingTasks = pendingTasksMapper.selectByCodeAndAssinessId(retreatCode, mgtUserId);

        //说明查询的之前的节点
        if (flowStatus == -1 || dbFlowstatus.equals(flowStatus)) {
            //如果审核人不是登录人  或者  当前登录人没有任务，返回审核记录
            if (!mgtUserId.equals(Long.valueOf(assigneeId)) || pendingTasks == null || pendingTasks.getIsHandle().equals(1)) {
                //当前登录人，没有要执行的任务
                vo.setIsShow(0);
            }
        }

        //当前登录人是申请人，并且，流程状态为0，则可以展示数据
        if (flowStatus == -1 && dbFlowstatus.equals(Retreat.FlowStatus.APPLY.getCode()) && mgtUserId.equals(retreat.getApplicatId())) {
            vo.setIsShow(1);
        }

        //订单已完成或已关闭
        if (!retreat.getStatus().equals(Retreat.Status.APPLICATION.getCode())) {
            //展示记录
            RetreatBill retreatBill = retreatBillMapper.selectByRetreatId(retreat.getId());
            vo.setIsShow(1);
            vo.setRetreatBill(retreatBill);
        }

        return AjaxResult.success(vo);
    }

    @Autowired
    @Qualifier("wechatCommonPayHandler")
    private CommonPayHandler commonPayHandler;

    /**
     * -提交退住申请
     * -护理组长审核
     * -法务人员提交
     * -结算员提交
     * -结算员组长审核
     * -副院长审核
     * -结算员调整账单提交
     *
     * @param retreatDto
     * @return
     */
    @Override
    @Transactional
    public AjaxResult submitRetreat(RetreatDto retreatDto) {

        //从当前线程中获取用户数据
        String subject = UserThreadLocal.getSubject();
        User user = JSON.parseObject(subject, User.class);
        /**
         * 判断当前操作人与登录人是否一致
         */
        if (retreatDto.getAssigneeId() == null || !retreatDto.getAssigneeId().equals(user.getId().toString())) {
            return AjaxResult.error("当前任务不属于你");
        }

        //查询退住数据
        Retreat retreat = retreatMapper.getRetreatByCode(retreatDto.getCode());

        //审核状态为1，护理员组长审核
        if (retreat.getFlowStatus().equals(Retreat.FlowStatus.APPLY_APPROVAL.getCode())) {
            //封装审核记录
            AccraditationRecord accraditationRecord = getAccraditationRecord(retreatDto,
                    user,
                    retreat,
                    "审批-申请审批",
                    AccraditationRecordConstant.RECORD_HANDLE_TYPE_AUDIT);

            //设置下一个审核人
            //找到法务部门编号--->通过编号查询法务中所有的员工（非leader）---->获取第一个人，找到这个人的id,然后查询对应的角色
            List<Long> userIdList = deptPostUserMapper.selectByDeptNo(RetreatConstant.LEGAL_DEPT_CODE);
            Long userId = userIdList.get(0);
            //查询下一个审核人的姓名和角色
            List<UserRoleVo> userRoleVoList = userRoleMapper.selectByUserId(userId);
            //待办任务，下个节点审核人 设置下个操作人--->法务
            UserRoleVo userRoleVo = userRoleVoList.get(0);

            //审核记录，设置下个节点审核人的角色和用户名
            accraditationRecord.setNextApprover(userRoleVo.getUserName());
            List<String> roleNameList = userRoleVoList.stream().map(x -> x.getRoleName()).collect(Collectors.toList());
            accraditationRecord.setNextApproverRole(StringUtils.join(roleNameList, ","));
            accraditationRecord.setNextApproverId(userRoleVo.getId());

            accraditationRecordMapper.insert(retreatDto.getAccraditationRecord());

            //保存或重新打开待办
            //下个处理人 处理过这个单子，把待办设置为未处理状态
            PendingTasks pendingTasks = pendingTasksMapper.selectByCodeAndAssinessId(retreat.getRetreatCode(), userId);
            if (pendingTasks != null) {
                pendingTasksMapper.updateIsHandle(retreat.getRetreatCode(), PendingTasksConstant.TASK_IS_HANDLE_UNTREATED, userId);
            } else {
                pendingTasks = getPendingTasks(retreat, RetreatConstant.ACCRADITATION_STEP_NO_TWO);
                pendingTasks.setAssignee(userRoleVo.getUserName());
                pendingTasks.setAssigneeId(userRoleVo.getId());
                pendingTasksMapper.insert(pendingTasks);
            }


            //修改之前的待办任务状态，为已处理
            pendingTasksMapper.updateIsHandle(retreat.getRetreatCode(), PendingTasksConstant.TASK_IS_HANDLE_FINISHED, user.getId());
            retreatMapper.updateRetreatByFlowStatus(retreat.getId(), Retreat.FlowStatus.RESCISSION_CONTRACT.getCode());
        }

        //审核状态为2，法务提交解除协议
        if (retreat.getFlowStatus().equals(Retreat.FlowStatus.RESCISSION_CONTRACT.getCode())) {

            RescissionContract rescissionContract = retreatDto.getRescissionContract();
            rescissionContract.setCreateTime(LocalDateTime.now());
            rescissionContract.setRescissionContractName(retreat.getName() + "的解除协议");
            //保存解除协议
            rescissionContractMapper.insert(rescissionContract);

            //封装审核记录
            AccraditationRecord accraditationRecord = getAccraditationRecord(retreatDto, user, retreat, "法务部处理-解除合同", AccraditationRecordConstant.RECORD_HANDLE_TYPE_PROCESSED);

            List<Long> userIdList = deptPostUserMapper.selectByDeptNo(RetreatConstant.SETTLEMENT_DEPT_CODE);
            Long userId = userIdList.get(0);
            //查询下一个审核人的姓名和角色
            List<UserRoleVo> userRoleVoList = userRoleMapper.selectByUserId(userId);

            //待办任务，下个节点审核人 设置下个操作人--->法务
            UserRoleVo userRoleVo = userRoleVoList.get(0);

            //审核记录，设置下个节点审核人的角色和用户名
            accraditationRecord.setNextApprover(userRoleVo.getUserName());
            List<String> roleNameList = userRoleVoList.stream().map(x -> x.getRoleName()).collect(Collectors.toList());
            accraditationRecord.setNextApproverRole(StringUtils.join(roleNameList, ","));
            accraditationRecord.setNextApproverId(userRoleVo.getId());
            accraditationRecordMapper.insert(accraditationRecord);

            PendingTasks pendingTasks = pendingTasksMapper.selectByCodeAndAssinessId(retreat.getRetreatCode(), userId);
            if (pendingTasks != null) {
                pendingTasksMapper.updateIsHandle(retreat.getRetreatCode(), PendingTasksConstant.TASK_IS_HANDLE_UNTREATED, userId);
            } else {
                pendingTasks = getPendingTasks(retreat, RetreatConstant.ACCRADITATION_STEP_NO_THREE);
                pendingTasks.setAssignee(userRoleVo.getUserName());
                pendingTasks.setAssigneeId(userRoleVo.getId());
                pendingTasksMapper.insert(pendingTasks);
            }

            //修改之前的待办任务状态，为已处理
            pendingTasksMapper.updateIsHandle(retreat.getRetreatCode(), PendingTasksConstant.TASK_IS_HANDLE_FINISHED, user.getId());
            retreatMapper.updateRetreatByFlowStatus(retreat.getId(), Retreat.FlowStatus.RECONCILIATION_BILL.getCode());
        }

        //审核状态为3，结算员调整账单
        if (retreat.getFlowStatus().equals(Retreat.FlowStatus.RECONCILIATION_BILL.getCode())) {
            //保存账单
            RetreatBill retreatBill = new RetreatBill();
            retreatBill.setRetreatId(retreat.getId());
            retreatBill.setBillJson(retreatDto.getBillJson());
            retreatBillMapper.insert(retreatBill);

            //封装审核记录
            AccraditationRecord accraditationRecord = getAccraditationRecord(retreatDto, user, retreat, "结算员处理-调整账单", AccraditationRecordConstant.RECORD_HANDLE_TYPE_PROCESSED);


            //设置下个操作人
            List<DeptPostUser> deptPostUserList = deptPostUserMapper.findDeptPostUserByUserId(user.getId());
            DeptPostUser deptPostUser = deptPostUserList.get(0);
            //申请人部门编号
            String deptNo = deptPostUser.getDeptNo();
            Dept dept = deptMapper.selectByDeptNo(deptNo);
            //部门领导id
            Long leaderId = dept.getLeaderId();
            //查询下一个审核人的姓名和角色
            List<UserRoleVo> userRoleVoList = userRoleMapper.selectByUserId(leaderId);
            //待办任务，下个节点审核人 设置下个操作人--->法务
            UserRoleVo userRoleVo = userRoleVoList.get(0);
            //审核记录，设置下个节点审核人的角色和用户名
            accraditationRecord.setNextApprover(userRoleVo.getUserName());
            List<String> roleNameList = userRoleVoList.stream().map(x -> x.getRoleName()).collect(Collectors.toList());
            accraditationRecord.setNextApproverRole(StringUtils.join(roleNameList, ","));
            accraditationRecord.setNextApproverId(userRoleVo.getId());

            accraditationRecordMapper.insert(retreatDto.getAccraditationRecord());

            PendingTasks pendingTasks = pendingTasksMapper.selectByCodeAndAssinessId(retreat.getRetreatCode(), userRoleVo.getId());
            if (pendingTasks != null) {
                pendingTasksMapper.updateIsHandle(retreat.getRetreatCode(), PendingTasksConstant.TASK_IS_HANDLE_UNTREATED, userRoleVo.getId());
            } else {
                //设置待办
                pendingTasks = getPendingTasks(retreat, RetreatConstant.ACCRADITATION_STEP_NO_FOUR);
                pendingTasks.setAssignee(userRoleVo.getUserName());
                pendingTasks.setAssigneeId(userRoleVo.getId());
                pendingTasksMapper.insert(pendingTasks);
            }
            //修改之前的待办任务状态，为已处理
            pendingTasksMapper.updateIsHandle(retreat.getRetreatCode(), PendingTasksConstant.TASK_IS_HANDLE_FINISHED, user.getId());
            retreatMapper.updateRetreatByFlowStatus(retreat.getId(), Retreat.FlowStatus.BILL_APPROVAL.getCode());
        }

        //审核状态为4，结算组长审核
        if (retreat.getFlowStatus().equals(Retreat.FlowStatus.BILL_APPROVAL.getCode())) {
            //封装审核记录
            AccraditationRecord accraditationRecord = getAccraditationRecord(retreatDto, user, retreat, "结算组长审批-账单审批", AccraditationRecordConstant.RECORD_HANDLE_TYPE_AUDIT);


            //设置下一个审核人--寻找副院长
            //找到法务部门编号--->通过编号查询法务中所有的员工（非leader）---->获取第一个人，找到这个人的id,然后查询对应的角色
            List<Long> userIdList = deptPostUserMapper.selectByDeptNo(RetreatConstant.DEAN_OFFICE_DEPT_CODE);
            Long userId = userIdList.get(0);
            //查询下一个审核人的姓名和角色
            //查询下一个审核人的姓名和角色
            List<UserRoleVo> userRoleVoList = userRoleMapper.selectByUserId(userId);
            //待办任务，下个节点审核人 设置下个操作人--->法务
            UserRoleVo userRoleVo = userRoleVoList.get(0);
            //审核记录，设置下个节点审核人的角色和用户名
            accraditationRecord.setNextApprover(userRoleVo.getUserName());
            List<String> roleNameList = userRoleVoList.stream().map(x -> x.getRoleName()).collect(Collectors.toList());
            accraditationRecord.setNextApproverRole(StringUtils.join(roleNameList, ","));
            accraditationRecord.setNextApproverId(userRoleVo.getId());
            accraditationRecordMapper.insert(retreatDto.getAccraditationRecord());

            //设置待办
            PendingTasks pendingTasks = pendingTasksMapper.selectByCodeAndAssinessId(retreat.getRetreatCode(), userRoleVo.getId());
            if (pendingTasks != null) {
                pendingTasksMapper.updateIsHandle(retreat.getRetreatCode(), PendingTasksConstant.TASK_IS_HANDLE_UNTREATED, userRoleVo.getId());
            } else {
                //设置待办
                pendingTasks = getPendingTasks(retreat, RetreatConstant.ACCRADITATION_STEP_NO_FIVE);
                pendingTasks.setAssignee(userRoleVo.getUserName());
                pendingTasks.setAssigneeId(userRoleVo.getId());
                pendingTasksMapper.insert(pendingTasks);
            }

            //修改之前的待办任务状态，为已处理
            pendingTasksMapper.updateIsHandle(retreat.getRetreatCode(), PendingTasksConstant.TASK_IS_HANDLE_FINISHED, user.getId());

            retreatMapper.updateRetreatByFlowStatus(retreat.getId(), Retreat.FlowStatus.RETREAT_APPROVAL.getCode());
        }

        //审核状态为5，副院长审核
        if (retreat.getFlowStatus().equals(Retreat.FlowStatus.RETREAT_APPROVAL.getCode())) {
            //封装审核记录
            AccraditationRecord accraditationRecord = getAccraditationRecord(retreatDto, user, retreat, "副院长审批-退住审批", AccraditationRecordConstant.RECORD_HANDLE_TYPE_AUDIT);

            //设置待办
//            PendingTasks pendingTasks = getPendingTasks(retreat, RetreatConstant.ACCRADITATION_STEP_NO_FIVE);

            //同样分配了结算员，分配给不同的结算员，还是分配给原来的结算员
            //假如，分配给了原来的结算员,在结算员的待办列表，只有一条数据
            /*PendingTasks pendingTasks = pendingTasksMapper.selectByRetreatCodeAndStepNo(retreat.getRetreatCode(), RetreatConstant.ACCRADITATION_STEP_NO_THREE);
            pendingTasksMapper.updateIsHandle(pendingTasks.getCode(), PendingTasksConstant.TASK_IS_HANDLE_UNTREATED, pendingTasks.getAssigneeId());*/
            pendingTasksMapper.updateIsHandleAndStepNo(retreat.getRetreatCode(), PendingTasksConstant.TASK_IS_HANDLE_UNTREATED, RetreatConstant.ACCRADITATION_STEP_NO_THREE);
            //设置下一个审核人--寻找结算员
            //找到法务部门编号--->通过编号查询法务中所有的员工（非leader）---->获取第一个人，找到这个人的id,然后查询对应的角色
            List<Long> userIdList = deptPostUserMapper.selectByDeptNo(RetreatConstant.SETTLEMENT_DEPT_CODE);
            Long userId = userIdList.get(0);
            //查询下一个审核人的姓名和角色
            List<UserRoleVo> userRoleVoList = userRoleMapper.selectByUserId(userId);

            //待办任务，下个节点审核人 设置下个操作人--->法务
            UserRoleVo userRoleVo = userRoleVoList.get(0);
            //审核记录，设置下个节点审核人的角色和用户名
            accraditationRecord.setNextApprover(userRoleVo.getUserName());
            List<String> roleNameList = userRoleVoList.stream().map(x -> x.getRoleName()).collect(Collectors.toList());
            accraditationRecord.setNextApproverRole(StringUtils.join(roleNameList, ","));
            accraditationRecord.setNextApproverId(userRoleVo.getId());

            accraditationRecordMapper.insert(retreatDto.getAccraditationRecord());

            //修改之前的待办任务状态，为已处理
            pendingTasksMapper.updateIsHandle(retreat.getRetreatCode(), PendingTasksConstant.TASK_IS_HANDLE_FINISHED, user.getId());

            retreatMapper.updateRetreatByFlowStatus(retreat.getId(), Retreat.FlowStatus.BILL_SETTLEMENT.getCode());

            //处理账单，应退&&转为余额
            RetreatBill retreatBill = retreatBillMapper.selectByRetreatId(retreat.getId());
            if (retreatBill != null && StringUtils.isNotEmpty(retreatBill.getBillJson())) {
                RetreatBillVo billVo = JSONUtil.toBean(retreatBill.getBillJson(), RetreatBillVo.class);
                //处理退款
                List<DueBack> dueBackList = billVo.getDueBackList();
                dueBackList.stream()
                        .filter(x -> x.getType() == 2)
                        .forEach(v -> {
                            TradingVo tradingVo = new TradingVo();
                            tradingVo.setTradingOrderNo(v.getTradingOrderNo());
                            commonPayHandler.refundTrading(tradingVo);
                        });
                //月度账单应退-->转为预缴款
                //账单退款金额
                BigDecimal amount = new BigDecimal(0);
                String code = null;
                Integer surplusDay = 0;
                String remark = null;
                for (DueBack dueBack : dueBackList) {
                    if (dueBack.getType() == 1) {
                        code = dueBack.getCode();
                        amount = dueBack.getAmount().subtract(dueBack.getRealAmount());
                        surplusDay = dueBack.getSurplusDay();
                        remark = dueBack.getRemark();
                        break;
                    }
                }

                RetreatClearingBillDto retreatClearingBillDto = new RetreatClearingBillDto();
                //账单编号
                retreatClearingBillDto.setBillNo(code);
                //账单扣减金额
                retreatClearingBillDto.setBillDeductions(amount);
                //实际退住时间
                retreatClearingBillDto.setLocalDateTime(retreat.getCheckOutTime());
                //退住天数surplusDay
                retreatClearingBillDto.setDay(surplusDay);
                //账单备注
                retreatClearingBillDto.setRemark(remark);
                //操作人id
                retreatClearingBillDto.setUserId(user.getId());
                //老人id
                retreatClearingBillDto.setElderId(retreat.getElderId());

                BalanceVo balanceVo = billVo.getBalanceVo();
                //余额扣减金额
                BigDecimal depositDeductions = balanceVo.getDepositAmount().subtract(balanceVo.getArrearsAmount());
                //押金备注
                retreatClearingBillDto.setDepositRemark(balanceVo.getRemark());
                //押金扣减金额
                retreatClearingBillDto.setDepositDeductions(depositDeductions.compareTo(BigDecimal.ZERO) == 1 ? depositDeductions : new BigDecimal(0));
                billService.retreatClearingBill(retreatClearingBillDto);
            }
        }

        //审核状态为6，结算员算清费用
        if (retreat.getFlowStatus().equals(Retreat.FlowStatus.BILL_SETTLEMENT.getCode())) {
            //封装审核记录
            AccraditationRecord accraditationRecord = getAccraditationRecord(retreatDto, user, retreat, "结算员处理-费用清算", AccraditationRecordConstant.RECORD_HANDLE_TYPE_PROCESSED);
            accraditationRecordMapper.insert(accraditationRecord);

            //设置待办  完成时间、状态，待办任务状态，为已处理
//            pendingTasksMapper.updateStatus(retreat.getRetreatCode(), LocalDateTime.now(), PendingTasksConstant.TASK_STATUS_FINISHED);

            PendingTasks pt = new PendingTasks();
            pt.setCode(retreat.getRetreatCode());
            pt.setFinishTime(LocalDateTime.now());
            pt.setStatus(PendingTasksConstant.TASK_STATUS_FINISHED);
            pt.setIsHandle(PendingTasksConstant.TASK_IS_HANDLE_FINISHED);
            pendingTasksMapper.updateByCode(pt);

            //修改退住单状态 status为为2(已完成)
            retreatMapper.updateStatus(retreat.getId(), Retreat.Status.FINISHED.getCode());

            //关闭账户，清空数据
            RetreatBill retreatBill = retreatBillMapper.selectByRetreatId(retreat.getId());
            balanceService.close(retreat.getElderId(), retreatBill.getRefundAmount());
            //修改我的申请单子为已完成
            applicationsMapper.updateStatus(retreat.getRetreatCode(), LocalDateTime.now(), Retreat.Status.FINISHED.getCode());

            //老人状态改为禁用
            Elder elder = new Elder();
            elder.setId(retreat.getElderId());
            elder.setStatus(0);
            elderMapper.updateByPrimaryKeySelective(elder);

        }

        return AjaxResult.success("提交成功");
    }

    @Autowired
    private ElderMapper elderMapper;

    /**
     * 封装审核记录
     *
     * @param retreatDto
     * @param user
     * @param retreat
     * @param currentStep
     * @return
     */
    private AccraditationRecord getAccraditationRecord(RetreatDto retreatDto, User user, Retreat retreat, String currentStep, Integer handleType) {
        //保存审核记录
        AccraditationRecord accraditationRecord = retreatDto.getAccraditationRecord();
        accraditationRecord.setApproverId(user.getId());
        accraditationRecord.setHandleType(handleType);
        accraditationRecord.setApproverName(user.getRealName());
        accraditationRecord.setBussniessId(retreat.getId());
        accraditationRecord.setCreateTime(LocalDateTime.now());
        accraditationRecord.setType(AccraditationRecordConstant.RECORD_TYPE_RETREAT);
        accraditationRecord.setStepNo(redisTemplate.boundValueOps(RECORD_STEP_NO_PRE + retreat.getId()).increment());
        accraditationRecord.setCurrentStep(currentStep);
        accraditationRecord.setAuditStatus(AccraditationRecordConstant.AUDIT_STATUS_PASS);
        return accraditationRecord;
    }

    /**
     * 封装待办对象
     *
     * @param retreat
     * @param accraditationStepNoOne
     * @return
     */
    private PendingTasks getPendingTasks(Retreat retreat, Integer accraditationStepNoOne) {
        PendingTasks pendingTasks = new PendingTasks();
        pendingTasks.setCode(retreat.getRetreatCode());
        pendingTasks.setApplicat(retreat.getApplicat());
        pendingTasks.setApplicatId(retreat.getApplicatId());
        pendingTasks.setTitle(retreat.getTitle());
        //退住
        pendingTasks.setType(PendingTasksConstant.TASK_TYPE_RETREAT);
        //审核中
        pendingTasks.setStatus(PendingTasksConstant.TASK_STATUS_APPLICATION);
        //未处理
        pendingTasks.setIsHandle(PendingTasksConstant.TASK_IS_HANDLE_UNTREATED);
        pendingTasks.setApplicationTime(retreat.getCreateTime());
        pendingTasks.setStepNo(accraditationStepNoOne);
        return pendingTasks;
    }

    @Autowired
    private BalanceService balanceService;

    /**
     * 获取操作步骤
     * TODO 江华去调试账单了，账单调完再调这块内容，审核记录的当前步骤   2023-07-20 10:17:24
     * @return
     */
    private String getRecordCurrentStep(Integer flowStatus) {
        String currentStep = "";

        switch (flowStatus) {
            case 0:
                currentStep = "申请退住";
                break;
            case 1:
                currentStep = "申请审批";
                break;
            case 2:
                currentStep = "解除合同";
                break;
            case 3:
                currentStep = "调整账单";
                break;
            case 4:
                currentStep = "账单审批";
                break;
            case 5:
                currentStep = "退住审批";
                break;
            case 6:
                currentStep = "费用清算";
                break;
        }
        return currentStep;
    }


    /**
     * 审核拒绝
     *
     * @param retreatCode 退住单code
     * @param reject      拒绝意见
     * @return
     */
    @Transactional
    @Override
    public AjaxResult auditReject(String retreatCode, String reject) {

        String subject = UserThreadLocal.getSubject();
        User user = JSON.parseObject(subject, User.class);

        //查询退住单
        Retreat retreat = retreatMapper.getRetreatByCode(retreatCode);
        if (retreat == null) {
            throw new BaseException("退住单不存在");
        }

        //修改退住单状态为3（已关闭）
        retreatMapper.updateStatus(retreat.getId(), Retreat.Status.CLOSED.getCode());

        //创建审核记录（状态改为已关闭）
        AccraditationRecord accraditationRecord = new AccraditationRecord();
        accraditationRecord.setApproverId(user.getId());
        accraditationRecord.setApproverName(user.getRealName());
        accraditationRecord.setBussniessId(retreat.getId());
        accraditationRecord.setCreateTime(LocalDateTime.now());
        accraditationRecord.setType(AccraditationRecordConstant.RECORD_TYPE_RETREAT);
        accraditationRecord.setOpinion("拒绝理由：" + reject);
        accraditationRecord.setBussniessId(retreat.getId());
        accraditationRecord.setAuditStatus(AccraditationRecordConstant.AUDIT_STATUS_REJECT);
        accraditationRecord.setCreateTime(LocalDateTime.now());
        accraditationRecord.setStepNo(redisTemplate.boundValueOps(RECORD_STEP_NO_PRE + retreat.getId()).increment());

        //查询下一个审核人的姓名和角色
        List<UserRoleVo> userRoleVoList = userRoleMapper.selectByUserId(user.getId());
        List<String> roleNameList = userRoleVoList.stream().map(x -> x.getRoleName()).collect(Collectors.toList());
        accraditationRecord.setApproverNameRole(StringUtils.join(roleNameList, ","));

        accraditationRecordMapper.insert(accraditationRecord);

        //修改待办任务为已关闭（status:已关闭，is_handle:已处理）
        PendingTasks pt = new PendingTasks();
        pt.setCode(retreatCode);
        pt.setFinishTime(LocalDateTime.now());
        pt.setStatus(PendingTasksConstant.TASK_STATUS_CLOSED);
        pt.setIsHandle(PendingTasksConstant.TASK_IS_HANDLE_FINISHED);
        pendingTasksMapper.updateByCode(pt);
        //修改我的申请状态和完成时间
        applicationsMapper.updateStatus(retreat.getRetreatCode(), LocalDateTime.now(), PendingTasksConstant.TASK_STATUS_CLOSED);

        return AjaxResult.success();
    }

    /**
     * 撤回
     *
     * @param retreatCode
     * @param flowStatus
     * @return
     */
    @Transactional
    @Override
    public AjaxResult revocation(String retreatCode, Integer flowStatus) {

        //获取登录用户
        String subject = UserThreadLocal.getSubject();
        User user = JSON.parseObject(subject, User.class);

        //查询退住单
        Retreat retreat = retreatMapper.getRetreatByCode(retreatCode);
        if (retreat == null) {
            throw new BaseException("退住单不存在");
        }

        //当前状态+1 == reteat.flowstatus
        if (retreat.getFlowStatus() > flowStatus) {
            throw new BaseException("退住单已审核，不能撤回");
        }

        //修改审核记录，is_handle为  未处理
        //查询审核记录
        AccraditationRecord accraditationRecord = accraditationRecordMapper.selectByBussniessIdAndApproverId(retreat.getId(), user.getId());
        Long nextApproverId = accraditationRecord.getNextApproverId();

        //保存审核记录
        AccraditationRecord record = new AccraditationRecord();
        record.setApproverId(user.getId());
        record.setApproverName(user.getRealName());
        List<UserRoleVo> userRoleVoList = userRoleMapper.selectByUserId(user.getId());
        if (userRoleVoList != null && userRoleVoList.size() > 0) {
            List<String> roleNameList = userRoleVoList.stream().map(x -> x.getRoleName()).collect(Collectors.toList());
            record.setApproverNameRole(StringUtils.join(roleNameList, ","));
        }
        record.setBussniessId(retreat.getId());
        record.setCreateTime(LocalDateTime.now());
        record.setType(AccraditationRecordConstant.RECORD_TYPE_RETREAT);
        record.setOpinion(user.getRealName() + "撤回了单子");
        record.setAuditStatus(AccraditationRecordConstant.AUDIT_STATUS_WITHDRAWS);
        record.setCreateTime(LocalDateTime.now());
        record.setStepNo(redisTemplate.boundValueOps(RECORD_STEP_NO_PRE + retreat.getId()).increment());
        accraditationRecordMapper.insert(record);

        //删除待办
        if (retreat.getFlowStatus().equals(Retreat.FlowStatus.BILL_SETTLEMENT.getCode())) {
            //修改结算的状态为已审核
            pendingTasksMapper.updateIsHandleAndStepNo(retreat.getRetreatCode(), PendingTasksConstant.TASK_IS_HANDLE_FINISHED, RetreatConstant.ACCRADITATION_STEP_NO_THREE);
        } else {
            pendingTasksMapper.deleteByCodeAndStepNo(retreat.getRetreatCode(), retreat.getFlowStatus());
        }

        //重新打开待办
        pendingTasksMapper.updateIsHandle(retreatCode, PendingTasksConstant.TASK_IS_HANDLE_UNTREATED, user.getId());

        //如果状态为3(则需要删除之前上传的合同)
        if (flowStatus.equals(Retreat.FlowStatus.RECONCILIATION_BILL.getCode())) {
            rescissionContractMapper.deleteByRetreatId(retreat.getId());
        }

        //如果状态为4,删除账单信息
        if (flowStatus.equals(Retreat.FlowStatus.BILL_APPROVAL.getCode())) {
            retreatBillMapper.deleteByByRetreatId(retreat.getId());
        }

        //修改退住单  状态回退 -1
        Integer state = flowStatus - 1;
        retreatMapper.updateRetreatByFlowStatus(retreat.getId(), state);

        return AjaxResult.success();
    }

    /**
     * 驳回
     *
     * @param retreatCode
     * @return
     */
    @Transactional
    @Override
    public AjaxResult disapprove(String retreatCode, String message) {

        //获取登录用户
        String subject = UserThreadLocal.getSubject();
        User user = JSON.parseObject(subject, User.class);

        //查询退住单
        Retreat retreat = retreatMapper.getRetreatByCode(retreatCode);
        if (retreat == null) {
            throw new BaseException("退住单不存在");
        }

        //保存审核记录
        AccraditationRecord accraditationRecord = new AccraditationRecord();
        accraditationRecord.setApproverId(user.getId());
        accraditationRecord.setApproverName(user.getRealName());
        accraditationRecord.setApproverNameRole(user.getRealName());
        accraditationRecord.setBussniessId(retreat.getId());
        accraditationRecord.setCreateTime(LocalDateTime.now());
        accraditationRecord.setType(AccraditationRecordConstant.RECORD_TYPE_RETREAT);
        accraditationRecord.setOpinion("驳回原因：" + message);
        accraditationRecord.setAuditStatus(AccraditationRecordConstant.AUDIT_STATUS_DISAPPROVE);
        accraditationRecord.setCreateTime(LocalDateTime.now());
        accraditationRecord.setStepNo(redisTemplate.boundValueOps(RECORD_STEP_NO_PRE + retreat.getId()).increment());
        accraditationRecordMapper.insert(accraditationRecord);

        //清空所有的待办任务
//        pendingTasksMapper.deleteByCode(retreat.getRetreatCode());
        //修改所有的待办为已处理
        pendingTasksMapper.updateIsHandleByCode(retreat.getRetreatCode(), PendingTasksConstant.TASK_IS_HANDLE_FINISHED);

        //删除解除协议，恢复合同生效
        rescissionContractMapper.deleteByRetreatId(retreat.getId());

        //删除账单数据
        retreatBillMapper.deleteByByRetreatId(retreat.getId());

        //修改退住状态为0
        retreatMapper.updateRetreatByFlowStatus(retreat.getId(), Retreat.FlowStatus.APPLY.getCode());

        return AjaxResult.success();


    }

    /**
     * 撤销
     *
     * @param retreatCode 退住编码
     * @return
     */
    @Transactional
    @Override
    public AjaxResult cancel(String retreatCode) {
        String subject = UserThreadLocal.getSubject();
        User user = JSON.parseObject(subject, User.class);

        //查询退住单
        Retreat retreat = retreatMapper.getRetreatByCode(retreatCode);
        if (retreat == null) {
            throw new BaseException("退住单不存在");
        }

        //修改退住单状态为3（已关闭）
        retreatMapper.updateStatus(retreat.getId(), Retreat.Status.CLOSED.getCode());

        //创建审核记录（状态改为已关闭）
        AccraditationRecord accraditationRecord = new AccraditationRecord();
        accraditationRecord.setApproverId(user.getId());
        accraditationRecord.setApproverName(user.getRealName());
        accraditationRecord.setBussniessId(retreat.getId());
        accraditationRecord.setCreateTime(LocalDateTime.now());
        accraditationRecord.setType(AccraditationRecordConstant.RECORD_TYPE_RETREAT);
        accraditationRecord.setOpinion(user.getRealName() + "撤销了申请");
        accraditationRecord.setBussniessId(retreat.getId());
        accraditationRecord.setAuditStatus(AccraditationRecordConstant.AUDIT_STATUS_CANCEL);
        accraditationRecord.setCreateTime(LocalDateTime.now());
        accraditationRecord.setStepNo(redisTemplate.boundValueOps(RECORD_STEP_NO_PRE + retreat.getId()).increment());

        //查询下一个审核人的姓名和角色
        List<UserRoleVo> userRoleVoList = userRoleMapper.selectByUserId(user.getId());
        List<String> roleNameList = userRoleVoList.stream().map(x -> x.getRoleName()).collect(Collectors.toList());
        accraditationRecord.setApproverNameRole(StringUtils.join(roleNameList, ","));

        accraditationRecordMapper.insert(accraditationRecord);


        //把还没有审核的待办任务，给删除了
        pendingTasksMapper.deleteByCodeAndIsHandle(retreat.getRetreatCode(), PendingTasksConstant.TASK_IS_HANDLE_UNTREATED);

        //修改待办任务为已关闭（status:已关闭，is_handle:已处理）
        pendingTasksMapper.updateStatus(retreat.getRetreatCode(), LocalDateTime.now(), PendingTasksConstant.TASK_STATUS_CLOSED);

        //修改我的申请状态和完成时间
        applicationsMapper.updateStatus(retreat.getRetreatCode(), LocalDateTime.now(), PendingTasksConstant.TASK_STATUS_CLOSED);

        return AjaxResult.success();
    }

    /**
     * 退住管理列表查询
     *
     * @return
     */
    @Override
    public AjaxResult selectByPage(RetreatReqDto retreatReqDto) {
        PageHelper.startPage(retreatReqDto.getPageNum(), retreatReqDto.getPageSize());
        Page<List<Retreat>> pages = retreatMapper.selectByPage(retreatReqDto);
        PageResponse<Retreat> of = PageResponse.of(pages, Retreat.class);
        return AjaxResult.success(of);
    }

}
